package com.eian.boot.common.id.generator.segment;

import com.eian.boot.common.id.exception.IdGenerationException;
import com.eian.boot.common.id.mapper.IdSegmentMapper;
import com.eian.boot.common.id.model.IdSegmentEntity;
import com.eian.boot.common.id.model.Segment;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * DB号段生成器
 *
 * @author alex.meng
 */
@Slf4j
@RequiredArgsConstructor
public class DbSegmentGenerator extends AbstractSegmentGenerator {

    /**
     * 最大重试次数
     */
    private static final int MAX_RETRY = 3;
    private final IdSegmentMapper idSegmentMapper;

    @Override
    protected Segment fetchNewSegment(String bizType) {
        for (int i = 0; i < MAX_RETRY; i++) {
            try {
                // 查询当前配置
                IdSegmentEntity entity = idSegmentMapper.selectByBizType(bizType);
                if (entity == null) {
                    throw new IdGenerationException(
                            "ID号段生成失败：未找到业务类型[" + bizType + "]的配置，请在id_segment表中初始化该业务类型"
                    );
                }

                // 乐观锁更新
                int affectedRows = idSegmentMapper.updateMaxId(bizType, entity.getStep(), entity.getVersion());
                if (affectedRows > 0) {
                    // 更新成功，构造号段
                    long currentMaxId = entity.getMaxId();
                    long newMaxId = currentMaxId + entity.getStep();
                    log.debug("获取DB号段成功：bizType={}, range=[{}, {})", bizType, currentMaxId, newMaxId);
                    return Segment.create(bizType, currentMaxId, newMaxId);
                }

                // 更新失败，说明有并发冲突，重试
                log.debug("DB号段获取冲突，重试：bizType={}, retry={}", bizType, i + 1);
            } catch (IdGenerationException e) {
                throw e;
            } catch (Exception e) {
                log.error("获取DB号段异常：bizType={}", bizType, e);
                throw new IdGenerationException("ID号段生成失败：" + e.getMessage(), e);
            }
        }

        throw new IdGenerationException("ID号段生成失败：超过最大重试次数，bizType=" + bizType);
    }
}

